﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Diagnostics;
using Elasticsearch.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net;

namespace FormsCmp
{
    class Program
    {
        const string patternTarget = @"^ +[\*-\^o] (名稱|區塊|項目|觸發程式) +";
        //const string patternAll = @"^ +[\*-\^o] (\S+)  +";
        //const string patternAll = @"^ +[\*-\^o] ([\S\s]+)  +";
        const string patternAll = @"^ +[\*-\^o] (.*?)  ";
        const string arrSplit = "----------";
        const string tempPath = @"G:\cmpTemp\";

        static int preLevel = 0;
        static List<int> blockLevelList = new List<int>();
        static string preMatchKey = "";
        static string preLine="";
        static string preVal = "";
        static string scriptStr = "";

        static bool preIsArr;
        static string preKey;
        static int blockLevel = 0;
        static bool arrFirst = false;
        static bool preHasProp = false;

        private static void Main(string[] args)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Console.OutputEncoding = Encoding.UTF8;

            //Test();
            //Print();
            MutBat();

            //string key = "VENDOR_PLANT";
            //string formName;
            //do
            //{
            //    Console.WriteLine("請輸入fmb名稱");
            //    formName = Console.ReadLine();
            //    if (formName == "q")
            //        return;
            //    try
            //    {
            //        Run(formName, key);
            //    }
            //    catch (Exception e)
            //    {
            //        Console.WriteLine(e.Message);
            //    }
            //} while (!string.IsNullOrEmpty(formName));

            //Run("IMRMB003", "imrm");
        }

        static void Test()
        {
            //HttpClient httpClient = new HttpClient();
            //httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            //StringContent strcontent = new StringContent("{\"query\":{\"multi_match\" : {\"query\":    \"vendor_plant\",\"fields\": [ \"*\" ]     }}}", Encoding.UTF8, "application/json");
            //var message = new HttpRequestMessage(HttpMethod.Post, "your address");
            ////设置cookie信息
            //message.Headers.Add("Cookie", "token=" + token);
            ////设置contetn
            //message.Content = strcontent;
            ////发送请求
            //var httpResponseHeaders = httpClient.SendAsync(message).Result;
            //client.PostAsync("http://192.168.0.102:9200",)
            WebClient wc = new WebClient();
            wc.Headers.Add("Content-Type", "application/json");
            var resp = wc.UploadString("http://192.168.0.102:9200/form*/_search","POST", "{\"query\":{\"multi_match\" : {\"query\":    \"vendor_plant\",\"fields\": [ \"*\" ]     }}}");
            Console.WriteLine(resp);
        }

        static void MutBat()
        {
            using (var file = new StreamReader($@"{tempPath}list.txt"))
            {
                while (!file.EndOfStream)
                {
                    var line = file.ReadLine();
                    if (!string.IsNullOrWhiteSpace(line))
                    {
                        Console.Write(line);
                        MutRun(line);
                        Console.WriteLine("--- success");
                    }
                }
            }
        }

        static void MutRun(string formName)
        {
            preLevel = 0;
            blockLevelList = new List<int>();
            preMatchKey = "";
            preLine = "";
            preVal = "";
            scriptStr = "";

            CopyForm(formName);
            CmpToTxt(formName);
            var json = TxtToJson(formName);
            var obj = ToObj(json);
            InsertElasticsearchBulk(obj);
        }

        static void Print()
        {
            string key = "VENDOR_PLANT";
            string formName;
            do
            {
                Console.WriteLine("請輸入fmb名稱");
                formName = Console.ReadLine();
                if (formName == "q")
                    return;
                try
                {
                    PrintRun(formName, key);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            } while (!string.IsNullOrEmpty(formName));
        }
        static void PrintRun(string formName,string key="")
        {

            CopyForm(formName);
            CmpToTxt(formName);
            var json = TxtToJson(formName);

            PrintResult(json, key);

            //Console.WriteLine(json);
            //Console.WriteLine(JsonString(json));
            //var obj = ToObj(json);
            //InsertElasticsearchBulk(obj);
        }


        static void CmpToTxt(string formName)
        {
            var process = new Process();
            process.StartInfo.FileName= @"C:\orant\bin\ifcmp60.exe";
            process.StartInfo.Arguments = @$"module={tempPath}{formName}.fmb LOGON=NO forms_doc=yes output_file={tempPath}{formName}.txt BATCH=YES Window_State=Minimize";
            process.StartInfo.UseShellExecute = false;        //是否使用操作系统shell启动
            process.StartInfo.RedirectStandardInput = true;   //接受来自调用程序的输入信息
            process.StartInfo.RedirectStandardOutput = true;  //由调用程序获取输出信息
            process.StartInfo.RedirectStandardError = true;   //重定向标准错误输出
            process.StartInfo.CreateNoWindow = true;          //不显示程序窗口
            process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            //process.StandardInput.WriteLine(cmd);
            //process.StandardInput.AutoFlush = true;
            process.Start();
            process.WaitForExit();//等待程序执行完退出进程
            process.Close();
            File.Delete(@$"{tempPath}{formName}.err");
        }
        static void CopyForm(string formName)
        {
            File.Copy($"//192.168.0.243\\miscn\\sinodev\\{formName.Substring(0,4)}\\{formName}.fmb", $@"{tempPath}{formName}.fmb",true);
        }

        static string JsonString(string json)
        {
            var obj = JsonSerializer.Deserialize<Form>(
                "{" + json + "}",
                new JsonSerializerOptions
                {
                    AllowTrailingCommas = true
                });

            return JsonSerializer.Serialize(obj);
        }

        static Form ToObj(string json)
        {
            return JsonSerializer.Deserialize<Form>(
                "{" + json + "}",
                new JsonSerializerOptions
                {
                    AllowTrailingCommas = true
                });
        }

        static void InsertElasticsearch(Form form)
        {
            var node = new Uri("http://192.168.0.102:9200");
            var settings = new ConnectionConfiguration(node);
            var client = new ElasticLowLevelClient(settings);

            IList<object> elaBulk = new List<object>();
            elaBulk.Add(new { index = new { _index = "forms", _id = form.Name } });
            elaBulk.Add(form);
            //var resp = client.Index<StringResponse>("forms", form.Name, PostData.Serializable(form));

            var elaForm = new Elastic.Form { Name = form.Name };

            //form trigger
            Elastic.FormTrigger elaFormTrigger = new Elastic.FormTrigger { Form = elaForm };
            foreach(var trigger in form.Triggers)
            {
                elaFormTrigger.Name = trigger.Name;
                elaFormTrigger.Content = trigger.Content;
                elaBulk.Add(new { index = new { _index = "form_triggers" } });
                elaBulk.Add(elaFormTrigger);
                //resp = client.Index<StringResponse>("form_triggers", PostData.Serializable(elaFormTrigger));
                //if (!resp.Success) Console.WriteLine($"form trigger fail: {trigger.Name}");
            }
            //form parameter
            Elastic.FormParameter elaFormParameter = new Elastic.FormParameter { Form = elaForm };
            foreach(var parameter in form.Parameters)
            {
                elaFormParameter.Name = parameter.Name;
                elaBulk.Add(new { index = new { _index = "form_parameters" } });
                elaBulk.Add(elaFormParameter);
                //resp = client.Index<StringResponse>("form_parameters", PostData.Serializable(elaFormParameter));
                //if (!resp.Success) Console.WriteLine($"form parameter fail: {parameter.Name}");
            }
            //form function
            Elastic.FormFunction elaFormFunction = new Elastic.FormFunction { Form = elaForm };
            foreach(var function in form.Functions)
            {
                elaFormFunction.Content = function.Content;
                elaFormFunction.Name = function.Name;
                elaBulk.Add(new { index = new { _index = "form_functions" } });
                elaBulk.Add(elaFormFunction);
                //resp = client.Index<StringResponse>("form_functions", PostData.Serializable(elaFormFunction));
                //if (!resp.Success) Console.WriteLine($"form function fail: {function.Name}");
            }
            //form record group
            Elastic.RecordGroup elaRecordGroup = new Elastic.RecordGroup { Form = elaForm };
            Elastic.RecordGroupItem elaRecordGroupItem = new Elastic.RecordGroupItem();
            foreach(var recordGroup in form.RecordGroups)
            {
                elaRecordGroup.Name = recordGroup.Name;
                elaRecordGroupItem.RecordGroup = elaRecordGroup;
                foreach (var item in recordGroup.Items)
                {
                    elaRecordGroupItem.Name = item.Name;
                    elaBulk.Add(new { index = new { _index = "form_record_group_items" } });
                    elaBulk.Add(elaRecordGroupItem);
                    //resp = client.Index<StringResponse>("form_record_group_items", PostData.Serializable(elaRecordGroupItem));
                    //if (!resp.Success) Console.WriteLine($"form record group item fail: {recordGroup.Name}.{item.Name}");
                }
            }
            //block
            Elastic.Block elaBlock = new Elastic.Block {Form=elaForm };
            Elastic.BlockTrigger elaBlockTrigger = new Elastic.BlockTrigger();
            Elastic.Item elaItem = new Elastic.Item ();
            Elastic.ItemTrigger elaItemTrigger = new Elastic.ItemTrigger();
            foreach (var block in form.Blocks)
            {
                elaBlock.Name = block.Name;
                //block trigger
                elaBlockTrigger.Block = elaBlock;
                foreach (var blockTrigger in block.Triggers)
                {
                    elaBlockTrigger.Content = blockTrigger.Content;
                    elaBlockTrigger.Name = blockTrigger.Name;
                    elaBulk.Add(new { index = new { _index = "form_block_triggers" } });
                    elaBulk.Add(elaBlockTrigger);
                    //resp = client.Index<StringResponse>("form_block_triggers", PostData.Serializable(elaBlockTrigger));
                    //if (!resp.Success) Console.WriteLine($"form record group item fail: {block.Name}.{elaBlockTrigger.Name}");
                }
                //block item
                elaItem.Block = elaBlock;
                foreach(var item in block.Items)
                {
                    //item
                    elaItem.ColName = item.ColName;
                    elaItem.Name = item.Name;
                    elaBulk.Add(new { index = new { _index = "form_items" } });
                    elaBulk.Add(elaItem);
                    //resp = client.Index<StringResponse>("form_items", PostData.Serializable(elaItem));
                    //if (!resp.Success) Console.WriteLine($"form item fail: {block.Name}.{elaItem.Name}");
                    //item trigger
                    elaItemTrigger.Item = elaItem;
                    foreach(var itemTrigger in item.Triggers)
                    {
                        elaItemTrigger.Content = itemTrigger.Content;
                        elaItemTrigger.Name = item.Name;
                        elaBulk.Add(new { index = new { _index = "form_item_triggers" } });
                        elaBulk.Add(elaItemTrigger);
                        //resp = client.Index<StringResponse>("form_item_triggers", PostData.Serializable(elaItemTrigger));
                        //if (!resp.Success) Console.WriteLine($"form item trigger fail: {block.Name}.{elaItem.Name}->{elaItemTrigger.Name}");
                    }
                }
                var resp = client.Bulk<StringResponse>(PostData.MultiJson(elaBulk));
                if (!resp.Success) Console.WriteLine(resp.Body);
            }
            //Console.WriteLine(resp);
        }

        static void InsertElasticsearchBulk(Form form)
        {
            
            var node = new Uri("http://192.168.0.102:9200");
            var settings = new ConnectionConfiguration(node);
            var client = new ElasticLowLevelClient(settings);

            IList<object> elaBulk = new List<object>();
            elaBulk.Add(new { index = new { _index = "forms", _id = form.Name } });
            elaBulk.Add(form);

            var elaForm = new Elastic.Form { Name = form.Name };

            //form trigger
            foreach (var trigger in form.Triggers)
            {
                Elastic.FormTrigger elaFormTrigger = new Elastic.FormTrigger { Form = elaForm,FormName=form.Name };
                elaFormTrigger.Name = trigger.Name;
                elaFormTrigger.Content = trigger.Content;
                elaBulk.Add(new { index = new { _index = "form_triggers" } });
                elaBulk.Add(elaFormTrigger);
            }
            //form parameter
            foreach (var parameter in form.Parameters)
            {
                Elastic.FormParameter elaFormParameter = new Elastic.FormParameter { Form = elaForm, FormName = form.Name };
                elaFormParameter.Name = parameter.Name;
                elaBulk.Add(new { index = new { _index = "form_parameters" } });
                elaBulk.Add(elaFormParameter);
            }
            //form function
            foreach (var function in form.Functions)
            {
                Elastic.FormFunction elaFormFunction = new Elastic.FormFunction { Form = elaForm, FormName = form.Name };
                elaFormFunction.Content = function.Content;
                elaFormFunction.Name = function.Name;
                elaBulk.Add(new { index = new { _index = "form_functions" } });
                elaBulk.Add(elaFormFunction);
            }
            //form record group
            foreach (var recordGroup in form.RecordGroups)
            {
                Elastic.RecordGroup elaRecordGroup = new Elastic.RecordGroup { Form = elaForm, FormName = form.Name };
                elaRecordGroup.Name = recordGroup.Name;
                foreach (var item in recordGroup.Items)
                {
                    Elastic.RecordGroupItem elaRecordGroupItem = new Elastic.RecordGroupItem { FormName = form.Name };
                    elaRecordGroupItem.RecordGroup = elaRecordGroup;
                    elaRecordGroupItem.Name = item.Name;
                    elaBulk.Add(new { index = new { _index = "form_record_group_items" } });
                    elaBulk.Add(elaRecordGroupItem);
                }
            }
            //block
            foreach (var block in form.Blocks)
            {
                Elastic.Block elaBlock = new Elastic.Block { Form = elaForm, FormName = form.Name };
                elaBlock.Name = block.Name;
                //block trigger
                foreach (var blockTrigger in block.Triggers)
                {
                    Elastic.BlockTrigger elaBlockTrigger = new Elastic.BlockTrigger { FormName = form.Name };
                    elaBlockTrigger.Block = elaBlock;
                    elaBlockTrigger.Content = blockTrigger.Content;
                    elaBlockTrigger.Name = blockTrigger.Name;
                    elaBulk.Add(new { index = new { _index = "form_block_triggers" } });
                    elaBulk.Add(elaBlockTrigger);
                }
                //block item
                foreach (var item in block.Items)
                {
                    Elastic.Item elaItem = new Elastic.Item { FormName = form.Name };
                    elaItem.Block = elaBlock;
                    //item
                    elaItem.ColName = item.ColName;
                    elaItem.Name = item.Name;
                    elaBulk.Add(new { index = new { _index = "form_items" } });
                    elaBulk.Add(elaItem);
                    //item trigger
                    foreach (var itemTrigger in item.Triggers)
                    {
                        Elastic.ItemTrigger elaItemTrigger = new Elastic.ItemTrigger { FormName = form.Name };
                        elaItemTrigger.Item = elaItem;
                        elaItemTrigger.Content = itemTrigger.Content;
                        elaItemTrigger.Name = itemTrigger.Name;
                        elaBulk.Add(new { index = new { _index = "form_item_triggers" } });
                        elaBulk.Add(elaItemTrigger);
                    }
                }
                
                //Console.WriteLine(JsonSerializer.Serialize(elaBulk));
            }
            var resp = client.Bulk<StringResponse>(PostData.MultiJson(elaBulk));
            if (!resp.Success) Console.WriteLine(resp.Body);
            //Console.WriteLine(resp);
        }
        static void PrintResult(string json,string key)
        {
            Regex searchReg = new Regex(key, RegexOptions.IgnoreCase);

            var obj = JsonSerializer.Deserialize<Form>(
                "{" + json + "}",
                new JsonSerializerOptions
                {
                    AllowTrailingCommas = true
                });

            IList<string> result = new List<string>();

            Console.Clear();
            Console.WriteLine(obj.Name);
            Console.WriteLine("=====================");
            Console.WriteLine("");

            
            foreach (var block in obj.Blocks)
            {
                if (block.Items != null)
                {
                    foreach (var item in block.Items)
                    {
                        if (searchReg.IsMatch(item.ColName ?? ""))
                            result.Add($"{block.Name}.{item.Name}");
                            //Console.WriteLine($"{block.Name}.{item.Name}");
                        else if (searchReg.IsMatch(item.Name ?? ""))
                            result.Add($"{block.Name}.{item.Name}");
                    }
                }

            }
            if (result.Count > 0)
            {
                Console.WriteLine("項目");
                Console.WriteLine("---------------------");
                foreach (var r in result)
                    Console.WriteLine(r);
                Console.WriteLine("");
            }


            result.Clear();
            if (obj.Triggers != null)
            {
                foreach (var trigger in obj.Triggers)
                {
                    if (searchReg.IsMatch(trigger.Content ?? ""))
                    {
                        //Console.WriteLine($"{obj.Name} --> {trigger.Name}");
                        result.Add($"{obj.Name} --> {trigger.Name}");
                    }
                }
            }
            foreach (var block in obj.Blocks)
            {
                if (block.Triggers != null)
                {
                    foreach (var trigger in block.Triggers)
                    {
                        if (searchReg.IsMatch(trigger.Content ?? ""))
                        {
                            //Console.WriteLine($"{obj.Name}.{block.Name} --> {trigger.Name}");
                            result.Add($"{obj.Name}.{block.Name} --> {trigger.Name}");
                        }
                    }
                }
                if (block.Items != null)
                {
                    foreach (var item in block.Items)
                    {
                        foreach (var trigger in item.Triggers)
                        {
                            if (searchReg.IsMatch(trigger.Content ?? ""))
                            {
                                //Console.WriteLine($"{obj.Name}.{block.Name}.{item.Name} --> {trigger.Name}");
                                result.Add($"{obj.Name}.{block.Name}.{item.Name} --> {trigger.Name}");
                            }
                        }
                    }
                }

            }
            if (result.Count > 0)
            {
                Console.WriteLine("觸發器");
                Console.WriteLine("---------------------");
                foreach (var r in result)
                    Console.WriteLine(r);
                Console.WriteLine("");
            }


            result.Clear();
            if (obj.Functions != null)
            {
                foreach (var function in obj.Functions)
                {
                    if (searchReg.IsMatch(function.Content ?? ""))
                    {
                        //Console.WriteLine($"{obj.Name} --> {function.Name}");
                        result.Add($"{obj.Name} --> {function.Name}");
                    }
                }
            }
            if (result.Count > 0)
            {
                Console.WriteLine("程式單元");
                Console.WriteLine("---------------------");
                foreach (var r in result)
                    Console.WriteLine(r);
                Console.WriteLine("");
            }


            result.Clear();
            if (obj.RecordGroups != null)
            {
                foreach (var recordGroup in obj.RecordGroups)
                {
                    if (recordGroup.Items != null)
                    {
                        foreach (var item in recordGroup.Items)
                        {
                            if (searchReg.IsMatch(item.Name ?? ""))
                            {
                                //Console.WriteLine($"{recordGroup.Name}");
                                result.Add($"{recordGroup.Name}.{item.Name}");
                            }
                        }
                    }
                }
            }
            if (result.Count > 0)
            {
                Console.WriteLine("記錄群組");
                Console.WriteLine("---------------------");
                foreach (var r in result)
                    Console.WriteLine(r);
                Console.WriteLine("");
            }


            //Console.WriteLine(json);

            //Trims();

            Console.WriteLine("=====================");
        }


        static string TxtToJson(string formName)
        {
            IList<string> result = new List<string>();
            blockLevelList.Add(0);

            using (var file = new StreamReader(@$"{tempPath}{formName}.txt", Encoding.GetEncoding("BIG5")))
            {
                //preLine = file.ReadLine();
                int i = 1;

                while (!file.EndOfStream)
                {
                    var line = file.ReadLine();
                    var r = HanddleLine3(line,i);
                    if (!string.IsNullOrEmpty(r))
                    {
                        result.Add(r);
                    }
                    i++;
                }
            }
            if (preLine == arrSplit)
            {
                result.Add("]");
            }
            else if (!string.IsNullOrWhiteSpace(preMatchKey))
            {
                result.Add($"\"{preMatchKey}\":{(IsArr(ToKeyName(preMatchKey)) ? "[]" : ("\"" + preVal + "\""))}");
            }

            var ret = string.Join("", result);
            ret = ret.Replace("],}", "]}");
            ret = ret.Replace("},]", "}]");

            return ret;
        }
        static string HanddleLine3(string line,int lineNo)
        {
            if (string.IsNullOrWhiteSpace(line)) return "";

            string result = "";

            var match = Regex.Match(line, patternAll);
            string matchKey = match.Groups[1].Value.Trim();
            int curLevel = (line.Length - line.TrimStart(' ').Length - 1) / 2;
            var curLine = line.Trim();

            //if (string.IsNullOrWhiteSpace(matchKey) && curLine != arrSplit)
            //    return "";


            string key = ToKeyName(preMatchKey);

            //if (preVal == "HRCOIL_NO")
            //{
            //    Console.WriteLine("");
            //}

            var hasPreMatchKey = !string.IsNullOrWhiteSpace(preMatchKey);
            var hasMatchKey = !string.IsNullOrWhiteSpace(matchKey);

            if (lineNo > 1)
            {
                if (hasPreMatchKey && curLine == arrSplit)
                {
                    if (curLevel > preLevel)
                        //result = $"\"{key}\":[{{";
                        result = $"\"{key}\":[";
                    else if (curLevel == preLevel)
                        //result = $"}},{{\"{key}\":\"{preVal}\"";
                        result = $"\"{key}\":{(IsArr(key) ? "[]" : ("\"" + preVal + "\""))}}},";
                    else
                        throw new Exception("none1");
                }
                else if (preLine == arrSplit && hasMatchKey)
                {
                    if (curLevel == preLevel)
                        //result = "";
                        result = "{";
                    else if (curLevel < preLevel)
                        //result = "}],";
                        result = "],";
                    else
                        throw new Exception("none2");
                }
                else if (hasPreMatchKey && hasMatchKey)
                {
                    if (curLevel == preLevel)
                        result = $"\"{key}\":{(IsArr(key) ? "[]" : ("\"" + preVal + "\""))},";
                    else
                        throw new Exception("none3");
                }
                else if (preLine == arrSplit && curLine == arrSplit)
                {
                    if (curLevel < preLevel)
                        //result = "}]";
                        result = "]},";
                    else
                        throw new Exception("none4");
                }
                else if (hasPreMatchKey && !hasMatchKey && curLine != arrSplit)
                {
                    scriptStr = "";
                    result = $"\"{key}\":\"";
                }
                else if (hasMatchKey && !hasPreMatchKey && preLine != arrSplit)
                {
                    scriptStr += preLine+" ";
                    result = $"{scriptStr.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\t"," ")}\",";
                }
                else if(!hasMatchKey && !hasPreMatchKey && preLine != arrSplit && curLine != arrSplit)
                {
                    scriptStr += preLine+" ";
                    result = "";
                }
                else
                    result = "";
                //throw new Exception("none5");


            }
            //if (!string.IsNullOrWhiteSpace(result)) Console.WriteLine($"{result}       {preLine}");

            preMatchKey = matchKey.Replace(" ","");
            preVal = Regex.Replace(line, @$"[\*\-\^o] {matchKey}", "").Trim().Replace("\\","\\\\").Replace("\"","\\\"").Replace("\t"," ");
            preLine = line.Trim().Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\t", " ");
            preLevel = curLevel;

            return result;
        }

        static string ToKeyName(string key)
        {
            switch (key)
            {
                case "觸發程式": return "Triggers";
                case "程式單元": return "Functions";
                case "區塊": return "Blocks";
                case "欄位名稱": return "ColName";
                case "名稱": return "Name";
                case "項目": return "Items";
                case "觸發程式文字":
                case "程式單元文字": return "Content";
                case "記錄群組": return "RecordGroups";
                case "直欄說明": return "Items";
                case "表單參數": return "Parameters";
                default:
                    return key;
            }
            //return key;
        }
        static bool IsArr(string key)
        {
            switch (key)
            {
                //case "子類別的資訊":
                //case "來源層次":
                //case "座標系統":
                //case "觸發程式":
                //case "警告":
                //case "連接 PL/SQL 程式庫":
                //case "區塊":
                //case "查詢資料原始欄位":
                //case "項目":
                //case "選項圓鈕":
                //case "元素的清單":
                //case "關係":
                //case "工作區":
                //case "圖形物件":
                //case "複合文字物件":
                //case "簡單的文字物件":
                //case "表單參數":
                //case "數值清單":
                //case "直欄對應的屬性":
                //case "功能表":
                //case "功能表的項目":
                //case "物件群組":
                //case "物件群組的子項":
                //case "程式單元":
                //case "特性類別":
                //case "記錄群組":
                //case "直欄說明":
                //case "視覺屬性":
                //case "視窗":
                case "Functions":
                case "Blocks":
                case "Items":
                case "RecordGroups":
                case "Parameters":
                case "Triggers":return true;
                default:
                    return false;
            }
        }

        class Form
        {
            public IList<Trigger> Triggers { get; set; }
            public IList<Trigger> Functions { get; set; }
            public IList<RecordGroup> RecordGroups { get; set; }
            public IList<Block> Blocks { get; set; }

            public IList<Other> Parameters { get; set; }
            public string Name { get; set; }
        }

        class Trigger
        {
            public string Name { get; set; }
            public string Content { get; set; }
        }

        class Block
        {
            public IList<Trigger> Triggers { get; set; }
            public IList<Item> Items { get; set; }
            public string Name { get; set; }
        }

        class Item
        {
            public IList<Trigger> Triggers { get; set; }
            public string ColName { get; set; }
            public string Name { get; set; }
        }

        class Other
        {
            public string Name { get; set; }
        }

        class RecordGroup
        {
            public string Name { get; set; }
            public IList<Other> Items { get; set; }
        }

        class Elastic
        {
            public class Form : Unit { }
            public class FormTrigger : Unit
            {
                public string Content { get; set; }
                public Form Form { get; set; }
            }

            public class Item: Unit
            {
                public string ColName { get; set; }
                public Block Block{ get; set; }
            }
            public class ItemTrigger : Unit
            {
                public string Content { get; set; }
                public Item Item { get; set; }
            }

            public class Block : Unit
            {
                public Form Form { get; set; }
            }
            public class BlockTrigger : Unit
            {
                public Block Block { get; set; }
                public string Content { get; set; }
            }


            public class RecordGroup : Unit 
            {
                public Form Form { get; set; }
            }
            public class RecordGroupItem : Unit
            {
                public RecordGroup RecordGroup { get; set; }
            }
            public class FormParameter : Unit 
            {
                public Form Form { get; set; }
            }
            public class FormFunction: FormTrigger{ }
            public class Unit
            {
                public string Name { get; set; }
                public string FormName { get; set; }
            }
        }
    }



    //static void Trims()
    //{
    //    string _preLine = "";
    //    int _preLevel = 0;
    //    int _curLevel = 0;
    //    var sets = new HashSet<string>();

    //    using (var file = new StreamReader(@$"E:\work\hrcoil_no\IMRMB002.txt", Encoding.GetEncoding("BIG5")))
    //    {
    //        while (!file.EndOfStream)
    //        {
    //            var line = file.ReadLine();
    //            if (!string.IsNullOrWhiteSpace(line) && line.Trim()== "----------" && _preLine.Trim() != "----------")
    //            {
    //                _curLevel = (line.Length - line.TrimStart(' ').Length - 1) / 2;
    //                if(_curLevel == _preLevel - 1)
    //                {
    //                    sets.Add(Regex.Replace(_preLine, @$"[\*\-\^o]", "").Trim());
    //                    //Console.WriteLine(_preLine);
    //                }
    //            }
    //            _preLine = line;
    //            _preLevel = _curLevel;
    //        }
    //    }

    //    foreach(var s in sets)
    //    {
    //        Console.WriteLine(s);
    //    }
    //}

    //static string Run(string formName,string key)
    //{
    //    Form form = new Form { Name = formName };
    //    IList<string> result = new List<string>();

    //    //using(var file = File.OpenText(@$"E:\work\hrcoil_no\{formName}.txt"))
    //    using (var file = new StreamReader(@$"E:\work\hrcoil_no\{formName}.txt",Encoding.GetEncoding("BIG5")))
    //    {
    //        while (!file.EndOfStream)
    //        {
    //            var line = file.ReadLine();
    //            var r = HanddleLine(line);
    //            if (!string.IsNullOrEmpty(r))
    //            {
    //                result.Add(r);
    //            }
    //        }
    //    }
    //    if (preIsArr)
    //    {
    //        result.Add("}]");
    //    }
    //    //Console.WriteLine("space:" + preLine);
    //    return string.Join("",result);
    //}

    //static string HanddleLine(string line)
    //{
    //    if (string.IsNullOrWhiteSpace(line))
    //    {

    //        return "";
    //    }


    //    var match = Regex.Match(line, patternAll);
    //    string replaceKey = "";
    //    string endSplit = "";
    //    string matchStr = match.Groups[1].Value.Trim();
    //    string customerStr = "";
    //    int curLevel = (line.Length - line.TrimStart(' ').Length - 1) / 2;
    //    string result = "";
    //    string val = Regex.Replace(line, @$"[\*\-\^o] {matchStr}", "").Trim();

    //    switch (matchStr)
    //    {
    //        case "名稱": replaceKey = "Name"; endSplit = ","; break;
    //        case "欄位名稱": replaceKey = "ColName"; endSplit = ","; break;
    //        case "來源名稱": replaceKey = "Other"; endSplit = ","; break;
    //        //case "位置": replaceKey = "Other"; endSplit = ","; break;
    //        case "觸發程式": replaceKey = "Triggers"; endSplit = ""; break;
    //        case "區塊": replaceKey = "Blocks"; endSplit = ""; break;
    //        case "程式單元": replaceKey = "Functions"; endSplit = ""; break;
    //        case "警告": replaceKey = "Alerts"; endSplit = ""; break;
    //        case "連接 PL/SQL 程式庫": replaceKey = "PlSqls"; endSplit = ""; break;
    //        case "選項圓鈕": replaceKey = "SingleBtns"; endSplit = ""; break;
    //        case "關係": replaceKey = "Relations"; endSplit = ""; break;
    //        case "工作區": replaceKey = "Spaces"; endSplit = ""; break;
    //        case "圖形物件": replaceKey = "RoundRects"; endSplit = ""; break;
    //        case "複合文字物件": replaceKey = "TextObjs"; endSplit = ""; break;
    //        case "簡單的文字物件": replaceKey = "STextObjs"; endSplit = ""; break;
    //        case "表單參數": replaceKey = "FormParamters"; endSplit = ""; break;
    //        case "數值清單": replaceKey = "Lovs"; endSplit = ""; break;
    //        case "直欄對應的屬性": replaceKey = "Lists"; endSplit = ""; break;
    //        case "功能表": replaceKey = "Tools"; endSplit = ""; break;
    //        case "功能表的項目": replaceKey = "ToolItems"; endSplit = ""; break;
    //        case "物件群組": replaceKey = "Objects"; endSplit = ""; break;
    //        case "物件群組的子項": replaceKey = "ObjectItems"; endSplit = ""; break;
    //        case "記錄群組": replaceKey = "RecordGroups"; endSplit = ""; break;
    //        case "直欄說明": replaceKey = "GroupItems"; endSplit = ""; break;
    //        case "視覺屬性": replaceKey = "Visuals"; endSplit = ""; break;
    //        case "視窗":
    //            if (string.IsNullOrEmpty(val))
    //            {
    //                replaceKey = "Windows";
    //                endSplit = "";
    //            }
    //            else
    //            {
    //                replaceKey = "Window";
    //                endSplit = ",";
    //            }
    //            break;
    //        case "子類別的資訊":
    //            replaceKey = "Others"; endSplit = ""; break;
    //        case "來源層次": replaceKey = "Others"; endSplit = ""; break;
    //        case "座標系統":
    //            if (string.IsNullOrEmpty(val))
    //            {
    //                replaceKey = "Others";
    //                endSplit = "";
    //            }
    //            else
    //            {
    //                replaceKey = "Other";
    //                endSplit = ",";
    //            }
    //            break;
    //        case "查詢資料原始欄位": replaceKey = "Cols"; endSplit = ""; break;
    //        case "項目": replaceKey = "Items"; endSplit = ""; break;
    //        case "觸發程式文字": 
    //        case "記錄群組查詢": 
    //        case "程式單元文字": customerStr = "\"Content\":\""; replaceKey = "customer"; break;
    //        case "在輸入查詢模式下執行":
    //        case "記錄群組取出大小":
    //        case "程式單元類型": customerStr = "\""; replaceKey = "customer"; break;
    //        case "註解": customerStr = "\"\""; replaceKey = "customer"; break;
    //        case "----------":
    //            if (curLevel == preLevel + 1)
    //                customerStr = "[{";
    //            else if (curLevel == preLevel)
    //                customerStr = "},{";
    //            else if (curLevel == preLevel - 1)
    //                customerStr = "}],";
    //            //customerStr = "["; 
    //            break;
    //        default:customerStr = line;break;
    //    }
    //    if (replaceKey != "")
    //    {
    //        if (customerStr == "")
    //            result= $"\"{replaceKey}\":{(endSplit == "" ? "" : "\"")}{val}{(endSplit == "" ? "" : "\"")}{endSplit}";
    //        else
    //            result= customerStr;
    //    }
    //    if (preIsArr)
    //    {
    //        result = "}]," + result;
    //    }

    //    //Console.WriteLine(matchStr);


    //    preLevel = curLevel;
    //    preIsArr = line.Trim() == "----------";
    //    preKey = replaceKey;

    //    //preLine = line;
    //    return result;
    //}

    //static string Run2(string formName, string key)
    //{
    //    IList<string> result = new List<string>();
    //    blockLevelList.Add(0);

    //    using (var file = new StreamReader(@$"E:\work\hrcoil_no\{formName}.txt", Encoding.GetEncoding("BIG5")))
    //    {
    //        preLine = file.ReadLine();


    //        while (!file.EndOfStream)
    //        {
    //            var line = file.ReadLine();
    //            var r = HanddleLine2(line);
    //            if (!string.IsNullOrEmpty(r))
    //            {
    //                result.Add(r);
    //            }
    //        }
    //    }
    //    if(preLine == "----------")
    //    {
    //        result.Add("}]");
    //    }

    //    var ret = string.Join("", result);
    //    ret = ret.Replace("],}", "]}");

    //    return ret;
    //}
    //static string HanddleLine2(string line)
    //{
    //    if (string.IsNullOrWhiteSpace(line)) return "";

    //    string result = "";

    //    var match = Regex.Match(line, patternAll);
    //    string matchKey = match.Groups[1].Value.Trim();
    //    int curLevel = (line.Length - line.TrimStart(' ').Length - 1) / 2;

    //    if (string.IsNullOrWhiteSpace(matchKey) && line.Trim() != "----------") 
    //        return "";
    //    string key = ToKeyName(preMatchKey);

    //    if (preVal == "HRCOIL_NO")
    //    {
    //        Console.WriteLine("");
    //    }

    //    //----------
    //    if (line.Trim()== "----------")
    //    {
    //        if(curLevel == blockLevel + 1)
    //        {
    //            if (!string.IsNullOrEmpty(preMatchKey))
    //            {
    //                result = $"\"{key}\":[{{";
    //                blockLevelList.Add(curLevel);
    //                blockLevel = curLevel;
    //            }
    //        }
    //        else if (curLevel == blockLevel - 1)
    //        {
    //            if (!string.IsNullOrEmpty(preMatchKey))
    //            {
    //                result = $"\"{key}\":\"{preVal}\"}}],";
    //                if (IsArr(key) && string.IsNullOrWhiteSpace(preVal))
    //                {
    //                    result = $"\"{key}\":[]}}],";
    //                }
    //                preHasProp = true;
    //            }
    //            else
    //            {
    //                result = "}],";
    //            }
    //            blockLevelList.Remove(blockLevelList.Count - 1);
    //            blockLevel = blockLevelList.Last();
    //        }
    //        else if (curLevel == blockLevel)
    //        {
    //            if (!string.IsNullOrEmpty(preMatchKey))
    //            {
    //                //result = $"{(arrFirst?"":"},")}{(preLevel==curLevel?"{":"")}\"{preMatchKey}\":\"{preVal}\"}},";
    //                result = $"\"{key}\":\"{preVal}\"}},{{";
    //                if (IsArr(key) && string.IsNullOrWhiteSpace(preVal))
    //                {
    //                    result = $"\"{key}\":[]}},{{";
    //                }
    //                //preHasProp = true;
    //            }
    //            //else
    //            //{
    //            //    //if(preHasProp)
    //            //    //    result = "}],";
    //            //}
    //        }
    //    }
    //    else
    //    {
    //        //if(curLevel == blockLevel)
    //        //{
    //        if (!string.IsNullOrEmpty(preMatchKey))
    //        {
    //            //result = $"{(arrFirst ? "" : "},")}{(preLevel == curLevel ? "{" : "")}\"{preMatchKey}\":\"{preVal}\",";
    //            result = $"\"{key}\":\"{preVal}\",";
    //            if(IsArr(key) && string.IsNullOrWhiteSpace(preVal))
    //            {
    //                result = $"\"{key}\":[],";
    //            }
    //            if (curLevel == preLevel - 1)
    //            {
    //                result = result + "}],";
    //            }
    //        }
    //        else if (preLine == "----------")
    //        {
    //            if (curLevel == preLevel - 1)
    //            {
    //                result = result + "}],";
    //                blockLevelList.Remove(blockLevelList.Count - 1);
    //                blockLevel = blockLevelList.Last();
    //            }
    //        }
    //        //}


    //    }

    //    //if (!string.IsNullOrWhiteSpace(result)) Console.WriteLine($"{result}       {preLine}");

    //    preMatchKey = matchKey;
    //    preVal = Regex.Replace(line, @$"[\*\-\^o] {matchKey}", "").Trim();
    //    preLine = line.Trim();
    //    preLevel = curLevel;

    //    return result;
    //}

}
